
#ifdef INT
#  define TYP INTEGER
#else
#ifdef FLOAT
#  define TYP REAL
#else
 #error "Need to give MACRO definition for element type : -DTYPE_INT or -DTYPE_FLOAT"
#endif
#endif


PROGRAM PROG_PRINC
!
!compilation : gfortran prog_princ.f90 -fbounds-check
!
IMPLICIT NONE
!DECLARATION DES PARAMETRES


	! LA TAILLE DES MATRICES EST ENTREE EN LIGNE DE COMMANDE LORS DE L' EXECUTION
	INTEGER :: p = 0

	INTEGER :: DIM1
	INTEGER :: F_COMPTEUR
	INTEGER :: I,J
	TYP :: S ! POUR LA GENERATION DE NOMBRE ALEATOIRE
	
	REAL :: INTERMEDIAIRE
	INTEGER :: VALEURMAX, VALEURMIN

	INTEGER :: order
	CHARACTER(len=32) :: arg
	
		
	!********************POUR Le stockage CSR
	TYP,DIMENSION(:),ALLOCATABLE :: U
    	INTEGER,DIMENSION(:,:),ALLOCATABLE :: INDICES !TABLEAU D'INDICES
   	TYP, DIMENSION (:), ALLOCATABLE :: VALUES
	INTEGER :: IERR

	TYP,DIMENSION(:),ALLOCATABLE :: V

	
	!**lecture des arguments en ligne de commande
	DO P=0,2
		CALL get_command_argument(p, arg)
		IF (LEN_TRIM(arg) == 0) exit 
		!WRITE (*,*) TRIM(arg)
		IF (p == 1) THEN
			read ( arg , '(i10)') DIM1
		ELSEIF (p == 2) THEN
			read ( arg , '(i10)') F_COMPTEUR
		ENDIF
	END DO


	!ALLOCATION DYNAMIQUE DE LA MEMOIRE 
	!********************POUR LE STOCKAGE COO
	ALLOCATE(VALUES(DIM1))
	ALLOCATE (INDICES(DIM1,2),STAT=IERR)
	ALLOCATE (U(DIM1))
	ALLOCATE (V(DIM1))



	IF(IERR.NE.0) STOP 'ERREUR pour l allocation des matrices/vecteurs!'

	VALEURMAX=100000
	VALEURMIN=-100000
	! PRENONS A DIAGONALE (COEFF ALEATOIRES)
	DO I=1,DIM1
		INDICES(I,1)=I
		INDICES(I,2)=I
		CALL RANDOM_NUMBER(INTERMEDIAIRE) 
		VALUES(I)=INTERMEDIAIRE*(VALEURMAX-VALEURMIN)+VALEURMIN 
		U(I)=I
	END DO

	!!!AFFICHONS LA MATRICE I        
	! DO I=1,DIM1
	 !  WRITE(*,*) VALUES(I)
	 !END DO
	
	
	CALL SPMV_COO(INDICES,VALUES,U,V,DIM1,F_COMPTEUR)

	! ON DESALLOUE TOUT CE QU'ON A ALLOUE
	DEALLOCATE(U)
	DEALLOCATE(INDICES)
	DEALLOCATE(VALUES)
	DEALLOCATE(V)

	!END DO

	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------ESPACE SUBROUTINES------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	CONTAINS


	!SUBROUTINES MATRICE CREUSE FORMAT COO
	!-----------------------------------------------------------------------------
	! Fonction : SPMV_COO
	! Description :- calcul le produit matrice_creuse/vecteur et enregistre le temps d'execution et les parametres de la matrice dans un fichier
	!                pour un stockage creux du type COOrdinate, on a une matrice qui contient les indices des valeurs non nuls de la matrice globale
	!                et un tableau qui contient les valeurs non nuls
	! Paramètres : - int **Indices, la matrice d'indices
	!              - T *Values, le tableau de valeurs non nuls
	!              - T *u, le vecteur multiplie
	!              - T *v, le vecteur resultat
	! 			 - int dim la dimension de la matrice
	! Retour: aucun
	!-----------------------------------------------------------------------------

	SUBROUTINE SPMV_COO(INDICES,VALUES,U,V,DIM1,F_COMPTEUR)
	!DECLARATIONS PARAMETRES
	REAL *8:: T1,T2,TEMPS_MOY=0.0
	INTEGER :: I,K,COMPTEUR=0
	CHARACTER*50 :: FORME="stockage COOrdinate"
	INTEGER, INTENT (IN) :: DIM1,F_COMPTEUR
	TYP,DIMENSION(:), INTENT (IN) :: VALUES
	TYP,DIMENSION(:), INTENT (IN) :: U
	INTEGER, DIMENSION (:,:), INTENT (IN) :: INDICES
	TYP,DIMENSION(:), INTENT (OUT):: V

	!CALCUL PRODUIT
	DO COMPTEUR=1,F_COMPTEUR
		!TOP CHRONO
		CALL CPU_TIME(T1)

		DO I=1,DIM1
			V(INDICES(I,1))=V(INDICES(I,1))+VALUES(I)*U(INDICES(I,2))
		     !WRITE (6,*) V(I)
		END DO

		!STOP CHRONO 
		CALL CPU_TIME(T2)
		TEMPS_MOY=T2 -T1+TEMPS_MOY
	END DO
	TEMPS_MOY=TEMPS_MOY/F_COMPTEUR
	WRITE(*,*) TEMPS_MOY


	END SUBROUTINE SPMV_COO

	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------END SUBROUTINES------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------
	!-------------------------------------------------------------------------------------------------------------------------------

END PROGRAM PROG_PRINC

!------------------------------------------------------------------------------
!MESSAGE D'ERREUR RETOURNER DANS LE TERMINAL
!a.out: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
!Abandon
!--------------------------------------------------------------------------------------

